package com.frame.ar.model;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import com.frame.ar.db.QueryParamsAnd;
import com.frame.ar.kit.ObjKit;
import com.frame.ar.vo.AjaxDone;
import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.ICallback;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;

/*******************************************
 * 作用描述：继承jfinal的Model抽象类，并进行公告方法封装
 ******************************************* 
 * @author LRC
 * @createDate 2015-9-12
 * @version v1.0
 * @param <M>
 * @updateRecord 格式：时间，作者，修改说明
 ******************************************* 
 * 
 */
public abstract class JFinalModel<M extends Model> extends Model<M> {

	/**
	 * model映射的表名
	 */
	protected String tableName;
	protected String primaryKey;
	
	/*******************************************
	 * 功能描述：获取model绑定的primaryKey
	 *******************************************
	 * @createDate 2015-9-20 by LRC
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public String getPrimaryKey(){
		if(primaryKey==null){
			//初始化tableName
			Table table = TableMapping.me().getTable(getClass());
			if(table!=null)
				primaryKey=table.getPrimaryKey();
			else
				primaryKey="";
		}
		return primaryKey;
	}
	/*******************************************
	 * 功能描述：获取model绑定的表名
	 *******************************************
	 * @createDate 2015-9-12 by LRC
	 * @return model绑定的表名
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public String getTableName(){
		if(tableName==null){
			//初始化tableName
			Table table = TableMapping.me().getTable(getClass());
			if(table!=null)
				tableName=table.getName();
			else
				tableName="";
		}
		return tableName;
	}

	/*******************************************
	 * 功能描述：根据查询参数获取数据集合
	 ******************************************* 
	 * @createDate 2015-9-12 by LRC
	 * @param qr
	 * @return 全字段数据列表 List
	 * @updateRecord 格式：时间，作者，修改说明
	 ******************************************* 
	 * 
	 */
	public List<M> findByQueryParams(QueryParamsAnd qr) {
		String sql = "select * from " + this.getTableName() + " where 1=1 ";
		sql = qr.getQueryString(sql);
		return find(sql, qr.getValue());
	}
	
	/*******************************************
	 * 功能描述：获得某些条件下的某个字段最大值
	 *******************************************
	 * @createDate 2015-9-12 by LRC
	 * @param column 最大值字段
	 * @param qr 查询参数
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public Object getMax(String column,QueryParamsAnd qr){
		String sql = "select max("+column+") as __max from " + this.getTableName() + " where 1=1 ";
		sql = qr.getQueryString(sql);
		Model m = findFirst(sql, qr.getValue());
		return m.get("__max");
	}
	
	/*******************************************
	 * 功能描述：根据查询参数删除数据对象
	 *******************************************
	 * @createDate 2015-9-13 by LRC
	 * @param qr
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public int deleteByQueryParams(QueryParamsAnd qr){
		String sql = "delete from " + this.getTableName() + " where 1=1 ";
		sql = qr.getQueryString(sql);
		return Db.update(sql);
	}
	
	/*******************************************
	 * 功能描述：分页查询参数信息
	 *******************************************
	 * @createDate 2015-9-13 by LRC
	 * @param pager
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public BJUIPager findByPage(BJUIPager pager){
		// 获取分页参数
		Integer pageSize = pager.getPageSize();
		Integer pageIndex = pager.getPageCurrent();
		
		// 设置默认值
		//pager.setOrderDefaultValue("orderid");
		String from = pager.getQr().getQueryString("from "+this.getTableName());
		// 查询用户列表
		Page<Record> args = Db.paginate(pageIndex, pageSize, "select * ",
				from, pager.getQr().getValue());
		
		pager.fillPageData(args,10);
		
		return pager;
	}
	
	/*******************************************
	 * 功能描述：保存BUJI框架提交上来的列表保存操作
	 *******************************************
	 * @createDate 2015-9-20 by LRC
	 * @param c
	 * @param dataPName
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public AjaxDone saveBJUIList(Controller c,String dataPName){
		AjaxDone done = new AjaxDone();
		
		
		return done;
	}
	
	/*******************************************
	 * 功能描述：进行表单保存操作
	 *******************************************
	 * @createDate 2015-9-20 by LRC
	 * @param c
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 2015-9-20 lrc 
	 * 	1)可做性能优化，如表中字段太多，提交的表单字段很少，可以提交参数作为填充目标
	 * 	2)做参数值类型转换，根据字段的类型做相应的处理
	 */
	public AjaxDone saveForm(Controller c){
		AjaxDone done = new AjaxDone();
		String[] columns = getTableColum();
		if(columns==null)return done;
		String key = getPrimaryKey();
		String tableName = getTableName();
		Record r = new Record();
		for(String col : columns){
			Object val = c.getPara(col);
			if(ObjKit.isNull(val))continue;
			r.set(col, val);
		}
		if(r.getColumnNames().length==0)return done;
		Object id = c.getPara(key);
		if(ObjKit.isNull(id)){
			//新增
			done.setStatusCode(Db.save(tableName, key, r) ? AjaxDone.OK : AjaxDone.ERROR);
		}else{
			r.set(key, id);
			//修改
			done.setStatusCode(Db.update(tableName, key, r) ? AjaxDone.OK : AjaxDone.ERROR);
		}
		id = r.get(key);
		done.setData(id.toString());
		return done;
	}
	/*******************************************
	 * 功能描述：进行表单保存操作
	 *******************************************
	 * @createDate 2015-9-20 by LRC
	 * @param c
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 2015-9-20 lrc 
	 * 	1)可做性能优化，如表中字段太多，提交的表单字段很少，可以提交参数作为填充目标
	 * 	2)做参数值类型转换，根据字段的类型做相应的处理
	 */
	public AjaxDone saveForm(JSONObject obj){
		AjaxDone done = new AjaxDone();
		String[] columns = getTableColum();
		if(columns==null)return done;
		String key = getPrimaryKey();
		String tableName = getTableName();
		Record r = new Record();
		for(String col : columns){
			Object val = obj.get(col);
			if(ObjKit.isNull(val))continue;
			r.set(col, val);
		}
		if(r.getColumnNames().length==0)return done;
		Object id = obj.get(key);
		if(ObjKit.isNull(id)){
			//新增
			done.setStatusCode(Db.save(tableName, key, r) ? AjaxDone.OK : AjaxDone.ERROR);
			Object keyValue = r.get(key);
			done.setData(keyValue!=null?keyValue.toString():"");
		}else{
			r.set(key, id);
			//修改
			done.setStatusCode(Db.update(tableName, key, r) ? AjaxDone.OK : AjaxDone.ERROR);
		}
		id = r.get(key);
		done.setData(id.toString());
		return done;
	}
	/*******************************************
	 * 功能描述：获取表列信息
	 *******************************************
	 * @createDate 2015-9-20 by LRC
	 * @return 
	 * @updateRecord 格式：时间，作者，修改说明
	 *******************************************
	 * 
	 */
	public String[] getTableColum(){
		Object columns = Db.execute(new ICallback() {
			@Override
			public Object call(Connection conn) throws SQLException {
				String table = getTableName();
				String sql = "select * from "+table+" where 1<>1 ";
				Statement st = conn.createStatement();
				if(!st.execute(sql))return null;
				ResultSet rs = st.getResultSet();
				ResultSetMetaData rsmd = rs.getMetaData();
				String[] columns = new String[rsmd.getColumnCount()];
				for(int i=0; i<columns.length; i++){
					columns[i] = rsmd.getColumnName(i+1);
				}
				return columns;
			}
		});
		return columns!=null ? (String[])columns : null;
	}
	
	/**
	 * 功能描述：从一个map类型的对象中获取数据
	 * @createDate 2015年10月12日 by LRC
	 * @param keys
	 * @param map 
	 * @updateRecord 格式：时间，作者，修改说明
	 * 
	 */
	public void copyValue(String[] keys,Object map){
		if(keys==null || map == null) return;
		
		if(map instanceof net.sf.json.JSONObject){
			net.sf.json.JSONObject obj = (net.sf.json.JSONObject)map;
			for(String key : keys){
				set(key, obj.get(key));
			}
			return;
		}
		
		if(map instanceof Map){
			Map<String,Object> obj = (Map<String,Object>)map;
			for(String key : keys){
				set(key, obj.get(key));
			}
			return;
		}
		
		if(map instanceof Record){
			Record obj = (Record)map;
			for(String key : keys){
				set(key, obj.get(key));
			}
			return;
		}
		
		if(map instanceof Controller){
			Controller obj = (Controller)map;
			for(String key : keys){
				set(key, obj.getPara(key));
			}
			return;
		}
	}
}
